package com.caigou.desensitization.strategy;

import com.caigou.desensitization.enums.SensitiveTypeEnums;
import com.caigou.desensitization.strategy.impl.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import javax.annotation.PostConstruct;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;

/**
 获取所有策略
 */
public class SensitiveContext {
	private static final Map<String, SensitiveStrategy> map =
			new ConcurrentHashMap<>();
	private static final Logger                         log =
			LoggerFactory.getLogger(SensitiveContext.class);

	static {
		map.put(SensitiveTypeEnums.DEFAULT.name(), new DefaultStrategyHandle());
		map.put(SensitiveTypeEnums.CHINESE_NAME.name(), new NameStrategyHandle());
		map.put(SensitiveTypeEnums.MOBILE.name(), new MobileStrategyHandle());
		map.put(SensitiveTypeEnums.FIXED_PHONE.name(), new FixedPhoneStrategyHandle());
		map.put(SensitiveTypeEnums.BANK_CARD.name(), new BankCardStrategyHandle());
		map.put(SensitiveTypeEnums.ID_CARD.name(), new IdCardStrategyHandle());
		map.put(SensitiveTypeEnums.EMAIL.name(), new EmailStrategyHandle());
		map.put(SensitiveTypeEnums.ADDRESS.name(), new AddressStrategyHandle());
	}

	public static SensitiveStrategy get(String sensitiveType) {
		SensitiveStrategy sensitiveStrategy = map.get(sensitiveType);
		Assert.notNull(sensitiveStrategy, "sensitiveStrategy no found!");
		return sensitiveStrategy;
	}

	@PostConstruct
	private void init() {
		//   SPI方式加载
		ServiceLoader<SensitiveStrategy> loader = ServiceLoader.load(SensitiveStrategy.class);
		if (!loader.iterator().hasNext()) {
			System.out.println("未发现自定义字段脱敏策略!");
		}
		for (SensitiveStrategy strategy : loader) {
			System.out.println("成功读取自定义字段脱敏策略 -> " + strategy.getType() + ":" + strategy.getClass());
			map.putIfAbsent(strategy.getType(), strategy);
		}
	}

	public static void printAllStrategies() {
		ObjectMapper mapper = new ObjectMapper();
		map.forEach((type, strategy) -> {
			Map<String, Object> jsonMap = new LinkedHashMap<>();
			jsonMap.put("name", type);
			jsonMap.put("class", strategy.getClass().getName());
			jsonMap.put("isUserCreate", !strategy.getClass().getPackage().getName()
			                                     .startsWith("com.caigou.desensitization.strategy" +
					                                                 ".impl")); // 判断是否为内置实现
			try {
				String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonMap);
				System.out.println(json);
			} catch (Exception e) {
				log.error("发生异常", e);
			}
		});
	}
}
